package com.panshi.service.impl;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.panshi.dao.ZxDao;
import com.panshi.service.ZxService;
import com.panshi.vo.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.DefaultTypedTuple;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.data.redis.core.ZSetOperations;
import org.springframework.stereotype.Service;

import java.lang.reflect.Type;
import java.util.*;

@Service
public class ZxServiceImpl implements ZxService {

    @Autowired
    ZxDao zxDao;

    @Autowired
    private RedisTemplate redisTemplate;

    //所有标题
    @Override
    public List<TitleVO> listTitleVOs() throws JsonProcessingException {
        ValueOperations operations = redisTemplate.opsForValue();
        List<TitleVO> list;
        if (redisTemplate.hasKey("title")) {
            String redisList = (String) operations.get("title");
            Type type = new TypeToken<List<TitleVO>>() {
            }.getType();
            list = new Gson().fromJson(redisList, type);
        } else {
            list = zxDao.listTitleVOs();
            ObjectMapper om = new ObjectMapper();
            redisTemplate.opsForValue().set("title", om.writeValueAsString(list));
        }
        return list;
    }

    //分页查询文章
    @Override
    public List<ArticleOkVO> listArticleOkVOs(int num) throws JsonProcessingException {
        List<ArticleOkVO> list;
        if (redisTemplate.hasKey("article")) {
            Set<ArticleOkVO> set = redisTemplate.opsForZSet().rangeByScore("article", num * 10 - 9, num * 10);
            list = new ArrayList<>(set);
        } else {
            list = zxDao.listAllArticleOkVOs();
            ZSetOperations.TypedTuple<ArticleOkVO> objectTypedTuple1;
            Set<ZSetOperations.TypedTuple<ArticleOkVO>> articleSet = new HashSet<ZSetOperations.TypedTuple<ArticleOkVO>>();
            int index = 1;
            for (ArticleOkVO ac :
                    list) {
                objectTypedTuple1 = new DefaultTypedTuple<ArticleOkVO>(ac, (double) index++);
                articleSet.add(objectTypedTuple1);
            }
            redisTemplate.opsForZSet().add("article", articleSet);
            Set<ArticleOkVO> set = redisTemplate.opsForZSet().rangeByScore("article", num * 10 - 9, num * 10);
            list = new ArrayList<>(set);
        }
        return list;
    }

    //查询所有文章
    @Override
    public List<ArticleOkVO> listAllArticleOkVOs() throws JsonProcessingException {
        return zxDao.listAllArticleOkVOs();
    }

    //文章底部 查询相关推荐总页数
    @Override
    public int countRecommendPage(int type) {
        return zxDao.countRecommendPage(type);
    }

    //文章底部 查询相关推荐
    @Override
    public List<ArticleOkVO> listRecommendArticleOkVOs(String page, String sort) {
        return zxDao.listRecommendArticleOkVOs(new Integer(page), sort);
    }

    //分类右边第二块 其他看点
    @Override
    public List<ArticleOkVO> listOtherArticleOkVOs() {
        return zxDao.listOtherArticleOkVOs();
    }

    //资讯右边第三块 大家都在看
    @Override
    public List<ArticleOkVO> listAllWatchArticleOkVOs() {
        return zxDao.listAllWatchArticleOkVOs();
    }

    @Override
    public List<ArticleOkVO> listSortLoadArticleOkVOs(int type, int page, int sort) {
        if (type == 1) {
            return zxDao.listNormalArticleOkVOs(page * 10 - 10, sort);
        } else if (type == 2) {
            return zxDao.listHotArticleOkVOs(page * 10 - 10, sort);
        } else if (type == 3) {
            return zxDao.listNewArticleOkVOs(page * 10 - 10, sort);
        } else {
            return null;
        }
    }

    //分类 热门文章
    @Override
    public List<ArticleOkVO> listHotArticleOkVOs(int page, int sort) throws JsonProcessingException {
        if (sort != -1) {
            return zxDao.listHotArticleOkVOs(page * 10 - 10, sort);
        } else {
            return zxDao.listHotArticleOkVOs(page * 10 - 10, -1);
        }
    }

    //分类 最新文章
    @Override
    public List<ArticleOkVO> listNewArticleOkVOs(int page, int sort) {
        if (sort != -1) {
            return zxDao.listNewArticleOkVOs(page * 10 - 10, sort);
        } else {
            return zxDao.listNewArticleOkVOs(page * 10 - 10, -1);
        }
    }


    //分类的相关推荐
    @Override
    public List<ArticleOkVO> listRelatedRecommendArticleOkVOs(int id) {
        return zxDao.listRelatedRecommendArticleOkVOs(id);
    }

    @Override
    public int countNewsPage() {
        return zxDao.countNewsPage();
    }

    @Override
    public List<ArticleT> findArticle(int page) {
        List<ArticleT> list;
        if (redisTemplate.hasKey("articlet")) {
            Set<ArticleT> set = redisTemplate.opsForZSet().rangeByScore("articlet", page * 10 - 9, page * 10);
            list = new ArrayList<>(set);
            System.out.println("缓存" + "\n" + list);
        } else {
            list = zxDao.findArticle();
            ZSetOperations.TypedTuple<ArticleT> objectTypedTuple1;
            Set<ZSetOperations.TypedTuple<ArticleT>> articleSet = new HashSet<ZSetOperations.TypedTuple<ArticleT>>();
            int index = 1;
            for (ArticleT ac :
                    list) {
                objectTypedTuple1 = new DefaultTypedTuple<ArticleT>(ac, (double) index++);
                articleSet.add(objectTypedTuple1);
            }
            redisTemplate.opsForZSet().add("articlet", articleSet);
            Set<ArticleT> set = redisTemplate.opsForZSet().rangeByScore("articlet", page * 10 - 9, page * 10);
            list = new ArrayList<>(set);
            System.out.println("data" + "\n" + list);
        }
        return list;
    }

    @Override
    public List<ArticleOk> findOkArticle(int page) {
        List<ArticleOk> list;
        if (redisTemplate.hasKey("articleokt")) {
            Set<ArticleOk> set = redisTemplate.opsForZSet().rangeByScore("articleokt", page * 10 - 9, page * 10);
            list = new ArrayList<>(set);
            System.out.println("缓存" + "\n" + list);
        } else {
            list = zxDao.findOkArticle();
            ZSetOperations.TypedTuple<ArticleOk> objectTypedTuple1;
            Set<ZSetOperations.TypedTuple<ArticleOk>> articleSet = new HashSet<ZSetOperations.TypedTuple<ArticleOk>>();
            int index = 1;
            for (ArticleOk ac :
                    list) {
                objectTypedTuple1 = new DefaultTypedTuple<ArticleOk>(ac, (double) index++);
                articleSet.add(objectTypedTuple1);
            }
            redisTemplate.opsForZSet().add("articleokt", articleSet);
            Set<ArticleOk> set = redisTemplate.opsForZSet().rangeByScore("articleokt", page * 10 - 9, page * 10);
            list = new ArrayList<>(set);
            System.out.println("data" + "\n" + list);
        }
        return list;
    }

    @Override
    public Boolean updateArticleT(ArticleT articleT) {
        List<ArticleOk> list = zxDao.findOkArticle();
        ZSetOperations.TypedTuple<ArticleOk> objectTypedTuple1;
        Set<ZSetOperations.TypedTuple<ArticleOk>> articleSet = new HashSet<ZSetOperations.TypedTuple<ArticleOk>>();
        int index = 1;
        for (ArticleOk ac :
                list) {
            objectTypedTuple1 = new DefaultTypedTuple<ArticleOk>(ac, (double) index++);
            articleSet.add(objectTypedTuple1);
        }
        redisTemplate.opsForZSet().add("articleokt", articleSet);
        return zxDao.updateArticleT(articleT);
    }

    @Override
    public Boolean insertArticle(ArticleT articleT) {
        List<ArticleOk> list = zxDao.findOkArticle();
        ZSetOperations.TypedTuple<ArticleOk> objectTypedTuple1;
        Set<ZSetOperations.TypedTuple<ArticleOk>> articleSet = new HashSet<ZSetOperations.TypedTuple<ArticleOk>>();
        int index = 1;
        for (ArticleOk ac :
                list) {
            objectTypedTuple1 = new DefaultTypedTuple<ArticleOk>(ac, (double) index++);
            articleSet.add(objectTypedTuple1);
        }
        redisTemplate.opsForZSet().add("articleokt", articleSet);
        return zxDao.insertArticle(articleT);
    }

    @Override
    public Boolean insertCollect(CollectVO collectVO) {
        List<ArticleOk> list = zxDao.findOkArticle();
        ZSetOperations.TypedTuple<ArticleOk> objectTypedTuple1;
        Set<ZSetOperations.TypedTuple<ArticleOk>> articleSet = new HashSet<ZSetOperations.TypedTuple<ArticleOk>>();
        int index = 1;
        for (ArticleOk ac :
                list) {
            objectTypedTuple1 = new DefaultTypedTuple<ArticleOk>(ac, (double) index++);
            articleSet.add(objectTypedTuple1);
        }
        redisTemplate.opsForZSet().add("articleokt", articleSet);
        return zxDao.insertCollect(collectVO);
    }
}
